﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Borg.Framework
{
    [Extension, Plug("Commands")]
    public class RuntimeCommands : IConsoleCommands
    {
        private readonly List<ICommand> _commands = new List<ICommand>();
        internal static readonly string lf = Environment.NewLine;

        public RuntimeCommands()
        {
            _commands.Add(new ListCommand());
            _commands.Add(new FindCommand());
            _commands.Add(new RegisterCommand());
            _commands.Add(new UnregisterCommand());
            _commands.Add(new CreateCommand());
            _commands.Add(new PlugCommand());
            _commands.Add(new UnplugCommand());
            _commands.Add(new ShutdownCommand());
            _commands.Add(new ReleaseCommand());
            _commands.Add(new PropertyCommand());
            _commands.Add(new UptimeCommand());
            _commands.Add(new CallCommand());
            _commands.Add(new OpenCommand());
            _commands.Add(new CloseCommand());
            _commands.Add(new SelectCommand());
            _commands.Add(new SetCommand());
        }

        internal static bool ContainsArgument(string value, string[] args)
        {
            return args.Any(arg => value == arg);
        }

        public static RepositoryElement[] Find(string[] command, int index, out string message)
        {
            message = string.Empty;

            if (command.Length >= (index + 2))
            {
                int i;
                string s = command[index + 1];
                s.Trim(new[] { '"', '\'' });

                switch (command[index])
                {
                    case "PluginInfo":
                        if (s != "*")
                        {
                            if (int.TryParse(s, out i))
                            {
                                var plugin = Runtime.Repository.PluginInfos.Find(i);

                                if (plugin != null)
                                    return new RepositoryElement[] {plugin};

                                message = string.Format("PluginInfo with the id {0} not found.", i);
                                break;
                            }

                            var plugins = Runtime.Repository.PluginInfos.Find(s);

                            if (plugins.Length == 0)
                                message = string.Format("PluginInfo with the name '{0}' not found.", command[index + 1]);

                            return plugins;
                        }

                        return Runtime.Repository.PluginInfos.ToArray();

                    case "ExtensionTypeInfo":
                        if (s != "*")
                        {
                            if (int.TryParse(s, out i))
                            {
                                var extensionType = Runtime.Repository.ExtensionTypeInfos.Find(i);

                                if (extensionType != null)
                                    return new RepositoryElement[] {extensionType};

                                message = string.Format("ExtensionTypeInfo with the id {0} not found.", i);
                                break;
                            }

                            var eti = Runtime.Repository.ExtensionTypeInfos.Find(s);

                            if (eti.Length == 0)
                                message = string.Format("ExtensionTypeInfo with the name '{0}' not found.",
                                                        command[index + 1]);

                            return eti;
                        }

                        return Runtime.Repository.ExtensionTypeInfos.ToArray();

                    case "PlugTypeInfo":
                        if (s != "*")
                        {
                            if (int.TryParse(s, out i))
                            {
                                var plugType = Runtime.Repository.PlugTypeInfos.Find(i);

                                if (plugType != null)
                                    return new RepositoryElement[] {plugType};

                                message = string.Format("PlugTypeInfo with the id {0} not found.", i);
                                break;
                            }

                            var pti = Runtime.Repository.PlugTypeInfos.Find(s);

                            if (pti.Length == 0)
                                message = string.Format("PlugTypeInfo with the name '{0}' not found.",
                                                        command[index + 1]);

                            return pti;
                        }

                        return Runtime.Repository.PlugTypeInfos.ToArray();

                    case "SlotTypeInfo":
                        if (s != "*")
                        {
                            if (int.TryParse(s, out i))
                            {
                                var slotType = Runtime.Repository.SlotTypeInfos.Find(i);

                                if (slotType != null)
                                    return new RepositoryElement[] {slotType};

                                message = string.Format("SlotTypeInfo with the id {0} not found.", i);
                                break;
                            }

                            var sti = Runtime.Repository.SlotTypeInfos.Find(s);

                            if (sti.Length == 0)
                                message = string.Format("SlotTypeInfo with the name '{0}' not found.",
                                                        command[index + 1]);

                            return sti;
                        }

                        return Runtime.Repository.SlotTypeInfos.ToArray();

                    case "ExtensionInfo":
                        if (s != "*")
                        {
                            if (int.TryParse(s, out i))
                            {
                                var extension = Runtime.Repository.ExtensionInfos.Find(i);

                                if (extension != null)
                                    return new RepositoryElement[] {extension};

                                message = string.Format("ExtensionInfo with the id {0} not found.", i);
                                break;
                            }

                            var ei = Runtime.Repository.ExtensionInfos.Find(s);

                            if (ei.Length == 0)
                                message = string.Format("ExtensionInfo with the name '{0}' not found.",
                                                        command[index + 1]);

                            return ei;
                        }

                        return Runtime.Repository.ExtensionInfos.ToArray();

                    case "Plug":
                        if (s != "*")
                        {
                            if (int.TryParse(s, out i))
                            {
                                var plug = Runtime.Repository.PlugInfos.Find(i);

                                if (plug != null)
                                    return new RepositoryElement[] {plug};

                                message = string.Format("Plug with the id {0} not found.", i);
                                break;
                            }

                            var pi = Runtime.Repository.PlugInfos.Find(s);

                            if (pi.Length == 0)
                                message = string.Format("Plug with the name '{0}' not found.", command[index + 1]);

                            return pi;
                        }

                        return Runtime.Repository.PlugInfos.ToArray();

                    case "SlotInfo":
                        if (s != "*")
                        {
                            if (int.TryParse(s, out i))
                            {
                                var slot = Runtime.Repository.SlotInfos.Find(i);

                                if (slot != null)
                                    return new RepositoryElement[] {slot};

                                message = string.Format("SlotInfo with the id {0} not found.", i);
                                break;
                            }

                            var si = Runtime.Repository.SlotInfos.Find(s);

                            if (si.Length == 0)
                                message = string.Format("SlotInfo with the name '{0}' not found.", command[index + 1]);

                            return si;
                        }

                        return Runtime.Repository.SlotInfos.ToArray();

                    case "ContractInfo":
                        if (s != "*")
                        {
                            if (int.TryParse(s, out i))
                            {
                                var contract = Runtime.Repository.ContractInfos.Find(i);

                                if (contract != null)
                                    return new RepositoryElement[] {contract};

                                message = string.Format("ContractInfo with the id {0} not found.", i);
                                break;
                            }

                            var ci = Runtime.Repository.ContractInfos.Find(s);

                            if (ci.Length == 0)
                                message = string.Format("ContractInfo with the name '{0}' not found.",
                                                        command[index + 1]);

                            return ci;
                        }

                        return Runtime.Repository.ContractInfos.ToArray();

                    case "SlotDefinition":
                        if (s != "*")
                        {
                            if (int.TryParse(s, out i))
                            {
                                var slot = Runtime.Repository.SlotDefinitions.Find(i);

                                if (slot != null)
                                    return new RepositoryElement[] {slot};

                                message = string.Format("SlotDefinition with the id {0} not found.", i);
                            }
                            else
                            {
                                var definitions = Runtime.Repository.SlotDefinitions.Find(s);

                                if (definitions.Length == 0)
                                    message = string.Format("SlotDefinition with the name '{0}' not found.",
                                                            command[index + 1]);

                                return definitions;
                            }

                            break;
                        }

                        return Runtime.Repository.SlotDefinitions.ToArray();
                }
            }

            return new RepositoryElement[0];
        }

        public IEnumerable<ICommand> Commands
        {
            get { return _commands; }
        }
    }
}

